'''
Copyright (c) 2018 Qualcomm Technologies International, Ltd.
    Part of 6.3.0

A script to create a table of thermistor voltages vs temperature.
By default, the script creates a table based on the datasheet parameters for
the thermistor NCP15XH103, over the temperature range -40 to +85 degrees Celsius.
The script can be modified to generate data for other thermistors by providing
command line arguments.

The thermistor resistance R at temperature T can be calculated as:

R = R0 * e (BETA * (1/T - 1/T0))

Where
    R0 is the thermistor's reference resistance.
    T0 is the temperature at which the thermistor's reference resistance is
    calibrated (in Kelvin).
    BETA is the thermistor's beta constant
    e is the exponential function

The temperature on the dev boards is measured using a potential divider.
As the thermistor resistance varies with temperature, the voltage across the
thermistor also varies and the variation (measured with an ADC) can be converted
to temperature.

    V_DIVIDER
_________________
        |
        |
        -
       | |
       | | R_DIVIDER
       | |
        -
        |
        |   ---------------->--- to ADC
        |
        -
       | |
       | | Thermistor
       | |
        -
        |
        |
__________________
       0V

'''

def celsius_to_kelvin(celsius):
    ''' Convert a temperature in Celsius to kelvin '''
    return celsius + 273.15

def thermistor_resistance(temperature, constants):
    '''
    Calculate the thermistor resistance at a temperature.
        All input temperatures are in degrees Celsius.
    '''
    from math import exp
    inverse_t = (1.0 / celsius_to_kelvin(temperature))
    inverse_t0 = (1.0 / celsius_to_kelvin(constants.T0))
    return constants.R0 * exp(constants.BETA * (inverse_t - inverse_t0))

def thermistor_voltage_mv(temperature, constants):
    '''
    Calculate the milli-voltage across the thermistor in the potential divider circuit.
        All input temperatures are in degrees Celsius.
    '''
    thermistor_r = thermistor_resistance(temperature, constants)
    voltage = constants.V_DIVIDER * thermistor_r / (thermistor_r + constants.R_DIVIDER)
    return int(voltage * 1000)

# File template
template = r'''/*!
\copyright  Copyright (c) {year} Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\brief      Thermistor temperature voltage lookup table.
\note       Auto-generated by {script} using constants:
                {constants}
*/

#include "types.h"

/*! \brief The temperature corresponding to the first entry in #thermistor_voltage_lookup_table */
#define THERMISTOR_TEMP_MIN {temp_min}
/*! \brief The temperature corresponding to the final entry in #thermistor_voltage_lookup_table */
#define THERMISTOR_TEMP_MAX {temp_max}

/*! \brief A table of expected thermistor milli-voltage against temperature in the
           range THERMISTOR_TEMP_MIN to THERMISTOR_TEMP_MAX degrees Celsius */
static const uint16 thermistor_voltage_lookup_table[THERMISTOR_TEMP_MAX-THERMISTOR_TEMP_MIN+1] = {{
{millivoltages}
}};
'''

def main():
    from datetime import datetime
    from argparse import ArgumentParser, RawDescriptionHelpFormatter
    parser = ArgumentParser(description=__doc__, formatter_class=RawDescriptionHelpFormatter)

    # Default values are taken from the NCP15XH103 thermistor
    parser.add_argument('--BETA', type=float, default=3380.0,
                        help="The thermistor beta constant.")
    parser.add_argument('--T0',   type=float, default=25.0,
                        help="The temperature (in degrees Celsius) at which the thermistor resistance is calibrated.")
    parser.add_argument('--R0', type=float, default=10000.0,
                        help="The thermistor's calibrated resistance in Ohms.")
    parser.add_argument("--V_DIVIDER", type=float, default=1.8,
                        help="The voltage driving the top of the measurement potential divider in Volts.")
    parser.add_argument("--R_DIVIDER", type=float, default=10000.0,
                        help="The resistance of the potential divider fixed value resistor in Ohms.")
    parser.add_argument("--TEMP_MIN", type=float, default=-40,
                        help="The minimum temperature (in degrees Celsius) for which data will be generated.")
    parser.add_argument("--TEMP_MAX", type=float, default=85,
                        help="The maximum temperature (in degrees Celsius) for which data will be generated.")
    args = parser.parse_args()

    # Iterate over the operating temperature.
    millivoltages = []
    for t in range(args.TEMP_MIN, args.TEMP_MAX+1):
        millivoltages.append("    " + str(thermistor_voltage_mv(t, args)) + ", // " + str(t) + "C")

    format_dict = dict( script=__file__,
                        constants=str(args),
                        year=datetime.now().year,
                        temp_min=args.TEMP_MIN,
                        temp_max=args.TEMP_MAX,
                        millivoltages='\n'.join(millivoltages))

    print template.format(**format_dict)

if __name__ == "__main__":
    main()
